package it.eng.area118.mdocommon.android.network;

import it.eng.area118.mdocommon.Network;
import it.eng.area118.mdocommon.android.log.BasicLogger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class AndroidNetworkService implements Network {

	private List<NetworkListener> listeners;

	private ConnectivityManager connectivityManager;

	private List<NetworkData<?>> pendingEvents;

	private AtomicReference<NetworkData<?>> networkDataReference = new AtomicReference<NetworkData<?>>(
			null);

	public AndroidNetworkService(ConnectivityManager connectivityManager) {
		listeners = new ArrayList<NetworkListener>();
		pendingEvents = new ArrayList<NetworkData<?>>();
		this.connectivityManager = connectivityManager;
		updateNetworkData(NetworkUtils.createNetworkData(connectivityManager));
	}

	@Override
	public void init() {

	}

	@Override
	public NetworkData<?> getNetworkData() {

		return NetworkUtils.createNetworkData(connectivityManager);

	}

	@Override
	public void destroy() {
		// TODO;

	}

	@Override
	public void addConnectionChangedListener(NetworkListener listener) {
		BasicLogger.writeLog(NETWORK_SERVICE, "adConnectionChangedListener");
		listeners.add(listener);
	}

	@SuppressWarnings("unchecked")
	@Override
	public synchronized void updateNetworkData(NetworkData<?> newNetworkData) {
		NetworkData<NetworkInfo> old = (NetworkData<NetworkInfo>) networkDataReference
				.getAndSet(newNetworkData);

		if (listeners.size() == 0) {
			pendingEvents.add(newNetworkData);
		} else {
			notifyPendingEvents();
			notifyListeners(old, newNetworkData);
		}

	}

	private void notifyPendingEvents() {
		for (NetworkData<?> data : pendingEvents) {
			notifyListeners(null, data);
		}
		pendingEvents.clear();

	}

	private void notifyListeners(NetworkData<?> old,
			NetworkData<?> newNetworkData) {

		for (NetworkListener listener : listeners) {

			listener.onConnectionChanged(old, networkDataReference.get());

		}
	}
}
